/**
 * Copyright 2020 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.dbfly.mybatis.builder.additional;

import java.lang.reflect.Method;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.jianggujin.dbfly.mybatis.JConfiguration;
import com.jianggujin.dbfly.mybatis.builder.JParamConsts;
import com.jianggujin.dbfly.mybatis.constant.JIdGeneratorStrategy;
import com.jianggujin.dbfly.mybatis.entity.JEntity;
import com.jianggujin.dbfly.mybatis.util.JElementBuilder;
import com.jianggujin.dbfly.mybatis.util.JProviderHelper;
import com.jianggujin.dbfly.util.JDBFlyException;
import com.jianggujin.dbfly.util.JStringUtils;

public class JAdditionalProvider {
    public static final String PARAM_OLD = "old";
    public static final String PARAM_NEWER = "newer";

    /**
     * 批量插入
     * 
     * @param configuration
     * @param mapperClass
     * @param method
     * @param document
     * @param mapperElement
     */
    public void insertList(JConfiguration configuration, Class<?> mapperClass, Method method, Document document,
            Element mapperElement) {
        JEntity entity = JProviderHelper.resolveEntity(configuration, mapperClass, method);
        // 批量插入的时候，主键生成规则不允许是SQL语句形式
        if (entity.getIdColumns().stream()
                .anyMatch(item -> JIdGeneratorStrategy.IDENTITY == item.getIdGeneratorStrategy())) {
            throw new JDBFlyException("{}批量插入主键策略不允许使用SQL形式生成", entity.getEntityClass().getCanonicalName());
        }
        boolean support = configuration.getDBFlyConfiguration().getDialect().handleInsertListMapperMethod(configuration,
                mapperClass, method, document, mapperElement, entity);
        if (!support) {
            throw new JDBFlyException("当前方言不支持批量插入");
        }
    }

    /**
     * 根据主键集合删除
     * 
     * @param configuration
     * @param mapperClass
     * @param method
     * @param document
     * @param mapperElement
     */
    public void deleteByIds(JConfiguration configuration, Class<?> mapperClass, Method method, Document document,
            Element mapperElement) {
        JEntity entity = JProviderHelper.resolveEntity(configuration, mapperClass, method);
        if (entity.getIdColumns().size() != 1) {
            throw new JDBFlyException("{}根据主键集合删除相关实体类只能包含一个主键属性", entity.getEntityClass().getCanonicalName());
        }

        Element deleteElement = JElementBuilder.buildDeleteElement(document, method);
        JProviderHelper.deleteFromTable(configuration, document, deleteElement, entity, null);
        whereIds(document, deleteElement, entity);
        mapperElement.appendChild(deleteElement);
    }

    /**
     * 根据主键集合查询
     * 
     * @param configuration
     * @param mapperClass
     * @param method
     * @param document
     * @param mapperElement
     */
    public void selectByIds(JConfiguration configuration, Class<?> mapperClass, Method method, Document document,
            Element mapperElement) {
        JEntity entity = JProviderHelper.resolveEntity(configuration, mapperClass, method);
        if (entity.getIdColumns().size() != 1) {
            throw new JDBFlyException("{}根据主键集合查询相关实体类只能包含一个主键属性", entity.getEntityClass().getCanonicalName());
        }
        String resultMap = JProviderHelper.checkAndCreateResultMap(configuration, document, mapperElement, entity);
        Element selectElement = JElementBuilder.buildSelectElement(document, method, resultMap, null);
        JProviderHelper.selectAllColumns(document, selectElement, entity);
        JProviderHelper.fromTable(configuration, document, selectElement, entity, null);
        whereIds(document, selectElement, entity);
        JProviderHelper.orderByDefault(document, selectElement, entity);
        mapperElement.appendChild(selectElement);
    }

    /**
     * 拼接条件
     *
     * @param sql
     * @param entityClass
     */
    private void whereIds(Document document, Element parentElement, JEntity entity) {
        Element whereElement = JElementBuilder.buildWhereElement(document);
        Element foreachElement = JElementBuilder.buildForeachElement(document,
                JStringUtils.format("{} in (", entity.getIdColumns().get(0).getColumn()), ")", "ids", "id", ",");
        JElementBuilder.appendChild(document, foreachElement, "#{id}");
        whereElement.appendChild(foreachElement);
        parentElement.appendChild(whereElement);
    }

    /**
     * 查询全部结果，支持分页
     * 
     * @param configuration
     * @param mapperClass
     * @param method
     * @param document
     * @param mapperElement
     */
    public void selectPageAll(JConfiguration configuration, Class<?> mapperClass, Method method, Document document,
            Element mapperElement) {
        JEntity entity = JProviderHelper.resolveEntity(configuration, mapperClass, method);
        String resultMap = JProviderHelper.checkAndCreateResultMap(configuration, document, mapperElement, entity);
        Element selectElement = JElementBuilder.buildSelectElement(document, method, resultMap, null);
        Element pageElement = JElementBuilder.buildElement(document, "page", "name", JParamConsts.PARAM_PAGE);
        JProviderHelper.selectAllColumns(document, pageElement, entity);
        JProviderHelper.fromTable(configuration, document, pageElement, entity, null);
        JProviderHelper.orderByDefault(document, pageElement, entity);
        selectElement.appendChild(pageElement);
        mapperElement.appendChild(selectElement);
    }

    /**
     * 根据Condition查询，支持分页
     * 
     * @param configuration
     * @param mapperClass
     * @param method
     * @param document
     * @param mapperElement
     */
    public void selectPageByCondition(JConfiguration configuration, Class<?> mapperClass, Method method,
            Document document, Element mapperElement) {
        JEntity entity = JProviderHelper.resolveEntity(configuration, mapperClass, method);
        String resultMap = JProviderHelper.checkAndCreateResultMap(configuration, document, mapperElement, entity);
        Element selectElement = JElementBuilder.buildSelectElement(document, method, resultMap, null);
        Element pageElement = JElementBuilder.buildElement(document, "page", "name", JParamConsts.PARAM_PAGE);
        JElementBuilder.appendChild(document, pageElement, "SELECT ");
        Element ifElement = JElementBuilder.buildIfElement(document,
                JStringUtils.format("{}.distinct", JParamConsts.PARAM_CONDITION));
        JElementBuilder.appendChild(document, ifElement, " DISTINCT ");
        pageElement.appendChild(ifElement);
        // 支持查询指定列
        JProviderHelper.conditionSelectColumns(document, pageElement, entity, JParamConsts.PARAM_CONDITION);
        JProviderHelper.fromTable(configuration, document, pageElement, entity, JParamConsts.PARAM_CONDITION);
        JProviderHelper.conditionWhereClause(document, pageElement, JParamConsts.PARAM_CONDITION);
        JProviderHelper.conditionOrderBy(document, pageElement, entity, JParamConsts.PARAM_CONDITION);
        selectElement.appendChild(pageElement);
        mapperElement.appendChild(selectElement);
    }

    /**
     * 查询，支持分页
     * 
     * @param configuration
     * @param mapperClass
     * @param method
     * @param document
     * @param mapperElement
     */
    public void selectPage(JConfiguration configuration, Class<?> mapperClass, Method method, Document document,
            Element mapperElement) {
        JEntity entity = JProviderHelper.resolveEntity(configuration, mapperClass, method);
        String resultMap = JProviderHelper.checkAndCreateResultMap(configuration, document, mapperElement, entity);
        Element selectElement = JElementBuilder.buildSelectElement(document, method, resultMap, null);
        Element pageElement = JElementBuilder.buildElement(document, "page", "name", JParamConsts.PARAM_PAGE);
        JProviderHelper.selectAllColumns(document, pageElement, entity);
        JProviderHelper.fromTable(configuration, document, pageElement, entity, JParamConsts.PARAM_RECORD);
        JProviderHelper.whereAllIfColumns(document, pageElement, entity, JParamConsts.PARAM_RECORD);
        JProviderHelper.orderByDefault(document, pageElement, entity);
        selectElement.appendChild(pageElement);
        mapperElement.appendChild(selectElement);
    }
}
